home *** CD-ROM | disk | FTP | other *** search
/ Aminet 31 / Aminet 31 (1999)(Schatztruhe)[!][Jun 1999].iso / Aminet / dev / c / vbccppcsrc.lha / vbcc / vlink / linker.c < prev    next >
C/C++ Source or Header  |  1999-03-07  |  46KB  |  1,476 lines

  1. /* $VER: vlink linker.c V0.6a (19.12.98)
  2.  *
  3.  * This file is part of vlink, a portable linker for multiple
  4.  * object formats.
  5.  * Copyright (c) 1997-99  Frank Wille
  6.  *
  7.  * vlink is freeware and part of the portable and retargetable ANSI C
  8.  * compiler vbcc, copyright (c) 1995-99 by Volker Barthelmann.
  9.  * vlink may be freely redistributed as long as no modifications are
  10.  * made and nothing is charged for it. Non-commercial usage is allowed
  11.  * without any restrictions.
  12.  * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
  13.  * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
  14.  *
  15.  *
  16.  * v0.6a (19.12.98) phx
  17.  *       Endianess of linking process will be determined by the type
  18.  *       of the first object.
  19.  *       Support for little endian object file formats. All read/write
  20.  *       operation on the object data is done in current endianess.
  21.  * v0.6  (24.10.98) phx
  22.  *       Take base register section offset from FFFuncs.baseoff.
  23.  * v0.5e (05.10.98) phx
  24.  *       Linking a ID_LIBARCH object requires its PriPointers to be
  25.  *       added to the global list: add_priptrs().
  26.  *       Call make_priptr_objects() after processing all objects in
  27.  *       linker_resolve has finished. If there are entries in the Pri-
  28.  *       Pointers list, then create some artificial sections (usually
  29.  *       constructor and destructor lists).
  30.  *       insertnode() <-> insertbehind().
  31.  * v0.5d (22.08.98) phx
  32.  *       Faster memory allocation can be activated by #define FASTALLOC.
  33.  *       Directories are only scanned if needed (AmigaOS filesystem is
  34.  *       too slow).
  35.  * v0.5c (08.07.98) phx
  36.  *       ID_ARTIFICIAL objects, i.e. objects created by the linker
  37.  *       are supported.
  38.  * v0.5  (27.06.98) phx
  39.  *       Target-specific linker symbol support.
  40.  * v0.4  (05.06.98) phx
  41.  *       Rewrote linker_join(). Now it can be guaranteed, that first
  42.  *       all code sections will be linked, then the data and finally
  43.  *       the bss sections.
  44.  *       Rewrote find_lnksect(). A lot more factors are now involved
  45.  *       in the decision if two sections can be coalesced: relative
  46.  *       references between the two, both are addressed base-relative,
  47.  *       or target-specific factors.
  48.  *       New functions for detection of relative references:
  49.  *       addrelref(), copyrelrefs(), checkrelrefs().
  50.  *       assign_common() finds a bss section for common symbols.
  51.  * v0.3b (02.05.98) phx
  52.  *       There were still infinite loops, if an object comes without
  53.  *       any section.
  54.  * v0.3  (16.04.98) phx
  55.  *       Resolving ADDR16_HA/HI/LO references to a relocatable symbol
  56.  *       didn't work (2 bytes of the next instructions were overwritten).
  57.  *       Fixed print_function_name(). Didn't work, if symbols had
  58.  *       a known size. Additionally, it can differentiate between
  59.  *       'no type', 'function' and 'object' now.
  60.  *       Avoid infinite loops for object units without section in
  61.  *       linker_join().
  62.  * v0.2  (07.03.98) phx
  63.  *       Base relative relocations must not be resolved, if the output
  64.  *       file is a relocatable object again. Base relative xrefs were
  65.  *       even completely corrupted and overwrote the following
  66.  *       instruction.
  67.  *       Library units are linked immediately and are no longer always
  68.  *       the last units in an output file.
  69.  *       Base relative relocation didn't work for baseoff=0x8000.
  70.  * v0.1  (27.02.98) phx
  71.  *       First version that seems to link AmigaOS ADOS and EHF
  72.  *       objects and libraries. Many common features, like linking
  73.  *       sections together which have relative references, are
  74.  *       still missing. Also, PowerPC-ELF32 support is about to come.
  75.  * v0.0  (02.12.97) phx
  76.  *       File created.
  77.  */
  78.  
  79.  
  80. #define LINKER_C
  81. #include "vlink.h"
  82.  
  83.  
  84. static char namebuf[FNAMEBUFSIZE];
  85.  
  86. static const char *filetypes[] = {
  87.   "unknown",
  88.   "object",
  89.   "executable",NULL,
  90.   "shared object",NULL,NULL,NULL,
  91.   "library"
  92. };
  93.  
  94. static const char *sec_names[] = {
  95.   "undefined","code","data","bss",NULL
  96. };
  97.  
  98. void linker_init(struct GlobalVars *);
  99. void linker_load(struct GlobalVars *);
  100. void linker_relrefs(struct GlobalVars *);
  101. void linker_resolve(struct GlobalVars *);
  102. void linker_join(struct GlobalVars *);
  103. void linker_copy(struct GlobalVars *);
  104. void linker_write(struct GlobalVars *);
  105. void linker_cleanup(struct GlobalVars *);
  106. char *getobjname(struct ObjectUnit *);
  107. void print_function_name(struct Section *,unsigned long);
  108. bool trace_sym_access(struct GlobalVars *,char *);
  109.  
  110. static void resolve_reloc(struct GlobalVars *,struct LinkedSection *,
  111.                           struct Section *,struct Reloc *);
  112. static void resolve_xref(struct GlobalVars *,struct LinkedSection *,
  113.                          struct Section *,struct XReference *);
  114. static void newreloc(struct LinkedSection *,struct LinkedSection *,
  115.                      unsigned long,int32,uint8);
  116. static void assign_common(struct GlobalVars *);
  117. static char *maplibrary(struct GlobalVars *,struct InputFile *);
  118. static char *searchlib(struct GlobalVars *,char *,int);
  119. static char *scan_directory(char *,char *,int);
  120. static void addrelref(struct RelRef **,struct Section *);
  121. static void copyrelrefs(struct RelRef **,struct Section *);
  122. static bool checkrelrefs(struct RelRef *,struct Section *);
  123. static struct LinkedSection *create_lnksect(struct GlobalVars *,char *,
  124.                                             uint8,uint8,uint8,uint8);
  125. static struct LinkedSection *find_lnksect(struct GlobalVars *,
  126.                                           struct Section *);
  127. static void combine_sections(struct LinkedSection *,struct Section *,uint8);
  128. static void print_symbol(FILE *,struct Symbol *);
  129. static char *protstring(uint8);
  130.  
  131.  
  132.  
  133. void linker_init(struct GlobalVars *gv)
  134. {
  135.   initlist(&gv->linkfiles);
  136.   initlist(&gv->selobjects);
  137.   initlist(&gv->libobjects);
  138.   initlist(&gv->sharedobjects);
  139.   gv->symbols = alloc_hashtable(SYMHTABSIZE);
  140.   initlist(&gv->pripointers);
  141.   gv->big_endian = -1;
  142. }
  143.  
  144.  
  145. void linker_load(struct GlobalVars *gv)
  146. /* load all objects and libraries into memory, identify their */
  147. /* format, then read all symbols and convert into internal format */
  148. {
  149.   struct InputFile *ifn = (struct InputFile *)gv->inputlist.first;
  150.   struct InputFile *nextifn;
  151.   struct LinkFile *lf;
  152.   uint8 *objptr;
  153.   char *objname;
  154.   unsigned long objlen;
  155.   int i,ff;
  156.  
  157.   if (gv->trace_file)
  158.     fprintf(gv->trace_file,"\nLoading files:\n\n");
  159.  
  160.   while (nextifn = (struct InputFile *)ifn->n.next) {
  161.     if (ifn->lib) {
  162.       if (!(objptr = (uint8 *)maplibrary(gv,ifn))) {
  163.         sprintf(namebuf,"-l%s",ifn->name);
  164.         error(8,namebuf);  /* cannot open -lxxx */
  165.       }
  166.     }
  167.     else {
  168.       if (objptr = (uint8 *)mapfile(ifn->name))
  169.         strcpy(namebuf,ifn->name);
  170.       else
  171.         error(8,ifn->name);  /* cannot open xxx */
  172.     }
  173.     objlen = *(size_t *)(objptr - sizeof(size_t));
  174.     objname = base_name(namebuf);
  175.  
  176.     /* determine the object's file format */
  177.     for (i=0,ff=ID_UNKNOWN; fff[i]; i++) {
  178.       if ((ff = (fff[i]->identify)(objname,objptr,objlen)) != ID_UNKNOWN)
  179.         break;
  180.     }
  181.     if (ff == ID_UNKNOWN)
  182.       error(11,objname);  /* File format not recognized */
  183.  
  184.     /* use endianess of first object read */
  185.     if (gv->big_endian < 0)
  186.       gv->big_endian = fff[i]->big_endian;
  187.     else if (gv->big_endian != fff[i]->big_endian)
  188.       error(61,objname);  /* endianess differs from previous objects */
  189.  
  190.     /* create new link file node */
  191.     lf = (struct LinkFile *)alloc(sizeof(struct LinkFile));
  192.     lf->pathname = allocstring(namebuf);
  193.     lf->filename = base_name(lf->pathname);
  194.     lf->data = objptr;
  195.     lf->length = objlen;
  196.     lf->format = (uint8)i;
  197.     lf->type = (uint8)ff;
  198.     if (gv->trace_file)
  199.       fprintf(gv->trace_file,"%s (%s %s)\n",namebuf,fff[i]->tname,
  200.                                             filetypes[ff]);
  201.  
  202.     /* read the file and convert into internal format */
  203.     fff[i]->readconv(gv,lf);
  204.     addtail(&gv->linkfiles,&lf->n);  /* not really needed */
  205.  
  206.     ifn = nextifn;  /* next input file */
  207.   }
  208. }
  209.  
  210.  
  211. void linker_resolve(struct GlobalVars *gv)
  212. /* Resolve all symbol references and pull the required objects into */
  213. /* the gv->selobjects list. */
  214. {
  215.   bool priptrs_made = FALSE;
  216.   struct ObjectUnit *obj = (s